这个字典库引起了 Python 之父的注意!你用过吗?
The following article is from Python开发者 Author 南风草木香
【导语】:本文介绍了Bi-Dictionary 库,即“Bi-directional Dictionary”双向字典,顾名思义,该库基于Python中的字典增加了由“值”访问键的功能,开发者可以通过值来反向查找键,使得处理字典更加方便。同时,该库也引起了 Python 之父 Guido 的注意,因此,很有必须学习Bi-Dictionary 库。
简介
字典是Python中最常见的数据结构之一,在日常开发中使用的频率很高。字典由一些键值对构成,我们只能通过键访问值,但是无法通过值访问键。目前有一个第三方库很好的解决了这个问题 - Bi-Dictionary,通过使用它,我们可以由值访问键。该库甚至引起了 Python 之父 Guido 的注意,因此这一特性未来可能会被加入到Python语法中。
安装
我们可以使用pip安装bidict库:
pip install bidict
随后,需要导入该库才能使用:
from bidict import bidict
简单使用
初步使用
我们首先通过创建一个字典,该字典的键为国家的简称,值为国家的全名,再用bidict初始化这个字典:
country_abbr_bidict = bidict({'USA': 'The United States of America'})
这样,我们只需要使用inverse()方法,就可以通过国家全称获取国家简称了:
from bidict import bidict
country_abbr_bidict = bidict({'USA': 'The United States of America'})
shortName = country_abbr_bidict.inverse['The United States of America']
print(shortName)
结果为:USA
我们可以对比下原字典和反转后的区别:
from bidict import bidict
country_abbr_bidict = bidict({'USA': 'The United States of America'})
print(country_abbr_bidict)
print(country_abbr_bidict.inverse)
结果显示,inverse()方法反转了原字典的键值位置:
bidict({'USA': 'The United States of America'})
bidict({'The United States of America': 'USA'})
为何不使用Python的字典呢?
我们也可以在字典中把键值互换,再存储一份数据,这样也能实现与bidict相同的效果。我们来尝试一下:
country_abbr_dict = {
'USA': 'The United States of America',
'The United States of America': 'USA'
}
如果我们想把USA
更新成US
,可以使用update()方法,像下面这样:
country_abbr_dict.update({
'US': 'The United States of America',
'The United States of America': 'US'
})
这似乎看起来很完美,但是字典仍然保留了原来的数据:
from bidict import bidict
country_abbr_dict = {
'USA': 'The United States of America',
'The United States of America': 'USA'
}
country_abbr_dict.update({
'US': 'The United States of America',
'The United States of America': 'US'
})
print(country_abbr_dict)
在结果中我们可以看到USA
也在字典中:
{'USA': 'The United States of America', 'The United States of America': 'US', 'US': 'The United States of America'}
为了避免这个问题,只能定义一个函数:
def update(d, key, val):
oldval = d.pop(key, object())
d.pop(oldval, None)
oldkey = d.pop(val, object())
d.pop(oldkey, None)
d.update({key: val, val: key})
country_abbr_dict = {
'USA': 'The United States of America',
'The United States of America': 'USA'
}
update(country_abbr_dict, 'US', 'The United States of America')
print(country_abbr_dict)
这样就可以成功更新字典了:
{'US': 'The United States of America', 'The United States of America': 'US'}
如果使用Bidict,就非常简单了:
country_abbr_bidict.inverse['The United States of America'] = 'US'
print(country_abbr_bidict)
bidict({'US': 'The United States of America'})
Bidict用起来,明显更方便!
Bidict的其他用途
在查找值之前,传入默认值
Bidict继承了Python字典中的大部分特性。例如,当我们想要通过键访问bidict中的某个值时,可以传入一个默认值。这样,如果bidict中没有该值,就会将默认值作为结果返回。
from bidict import bidict
country_abbr_bidict = bidict({
'US': 'The United States of America',
})
print(country_abbr_bidict.get('AU', 'Australia'))
结果就是我们传入的默认值:Australia
加入新的键值对
Bidict加入新键值对的方式与Python的原生字典一样,我们来试试:
from bidict import bidict
country_abbr_bidict = bidict({
'US': 'The United States of America',
})
country_abbr_bidict['AU'] = 'Australia'
country_abbr_bidict['CA'] = 'Canada'
print(country_abbr_bidict)
结果为:
bidict({'US': 'The United States of America', 'AU': 'Australia', 'CA': 'Canada'})
检验Bidict中是否有某个特定值
(1)我们可以使用in关键字来检查Bidict中是否有CA:
'CA' in country_abbr_bidict
我们可以得到一个布尔值,表示该键是否存在于Bidict中:True
(2)同样我们也可以检查Bidict中是否有某个值,
'Australia' in country_abbr_bidict.inverse
结果显示Bidict中有该值:True
Pop and Delete方法
除了上述特性外,我们还可以使用Pop and Delete方法。
(1)pop()方法可以从Bidict中弹出键值对
country_abbr_bidict.pop('AU')
会返回该键对应的值:Australia
我们再看看Bidict:country_abbr_bidict
发现里面没有AU这个键值对了:bidict({'US': 'The United States of America', 'CA': 'Canada'})
(2)delete()方法可以通过键或者值的方式删除键值对
del country_abbr_bidict.inverse['Canada']
print(country_abbr_bidict)
结果显示删除成功:bidict({'US': 'The United States of America'})
约束
Python的设计理念是当程序出现错误时,一定要显示出来,Bidict的设计也遵循了这一点。Bidict的一个约束是键、值都要唯一,这是因为值也有可能会被当作键使用。因此,当我们想在Bidict中加入一个新的键值对(该键值对的值已经被其他键使用),就会报错。例如,我们想把US - The United States of America
加入Bidict中,但是原字典中已有USA - The United States of America
了:
from bidict import bidict
country_abbr_bidict = bidict({
'USA': 'The United States of America',
})
country_abbr_bidict['US'] = 'The United States of America'
会产生如下错误:
Traceback (most recent call last):
File "F:/Documents/其他资料/pythonprojects/01practice/app.py", line 5, in <module>
country_abbr_bidict['US'] = 'The United States of America'
File "F:\python\lib\site-packages\bidict\_bidict.py", line 67, in __setitem__
self.put(key, val, on_dup=self.on_dup)
File "F:\python\lib\site-packages\bidict\_bidict.py", line 93, in put
self._update([(key, val)], on_dup=on_dup)
File "F:\python\lib\site-packages\bidict\_base.py", line 455, in _update
dedup_result = self._dedup(key, val, on_dup)
File "F:\python\lib\site-packages\bidict\_base.py", line 350, in _dedup
raise ValueDuplicationError(val)
bidict.ValueDuplicationError: The United States of America
我们可以使用forceput()方法来避免这一错误:country_abbr_bidict.forceput('USA', 'The United States of America')
但是,如果出现了两个键的值相同这种情况,该方法会把原来的键覆盖:bidict({'US': 'The United States of America'})
其他特性
更新多个键值对
putall()方法可以同时加入多个键值对到Bidict中,但传入的参数必须是可迭代的。
country_abbr_bidict.putall([
('AU', 'Australia'),
('CA', 'Canada')
])
print(country_abbr_bidict)
结果显示加入成功:bidict({'USA': 'The United States of America', 'AU': 'Australia', 'CA': 'Canada'})
当某个键值对无法传入时,那么其他键值对也无法传入:
country_abbr_bidict = bidict({'US': 'United States of America'})
country_abbr_bidict.putall([
('AU', 'Australia'),
('CA', 'Canada'),
('US', 'The United States of America')
])
这里出现了报错:
Traceback (most recent call last):
File "F:/Documents/其他资料/pythonprojects/01practice/app.py", line 3, in <module>
country_abbr_bidict.putall([
File "F:\python\lib\site-packages\bidict\_bidict.py", line 179, in putall
self._update(items, on_dup=on_dup)
File "F:\python\lib\site-packages\bidict\_base.py", line 443, in _update
target._update(arg, kw, rbof=False, on_dup=on_dup)
File "F:\python\lib\site-packages\bidict\_base.py", line 455, in _update
dedup_result = self._dedup(key, val, on_dup)
File "F:\python\lib\site-packages\bidict\_base.py", line 343, in _dedup
raise KeyDuplicationError(key)
bidict.KeyDuplicationError: US
而其他键值对也没有传入到Bidict中:bidict({'US': 'United States of America'})
forceupdate()方法的优先级
如果我们想使用该方法传入多个键值对,对Bidict进行更新,那么就要注意传入数据的先后顺序了。
如果把USA放到最后,那么最终Bidict就会使用该键:
country_abbr_bidict = bidict({'US': 'United States of America'})
country_abbr_bidict.forceupdate([
('US', 'The United States of America'),
('USA', 'The United States of America')
])
结果为:bidict({'USA': 'The United States of America'})
如果把US放到最后,那么字典就会将US作为键。
country_abbr_bidict.forceupdate([
('USA', 'The United States of America'),
('US', 'The United States of America')
])
print(country_abbr_bidict)
结果为:bidict({'US': 'The United States of America'})
与其他数据结构交互
Bidict可以转换为其他数据结构,反之亦然。例如,我们可以把Bidict转换为字典:dict(country_abbr_bidict)
结果为:{'US': 'United States of America'}
我们再把字典转换为Bidict: bidict(dict(country_abbr_bidict))
结果为:bidict({'US': 'United States of America'})
结论
在本文中,我介绍了Bi-Dictionary库-双向字典,也称为Bidict。它不仅改进了Python字典的缺点,而且遵循了Python的设计原则。非常值得学习!
参考原文:
https://towardsdatascience.com/python-bi-dictionary-key-can-be-value-and-value-can-be-key-50715a2046af
- EOF -
↓推荐关注↓
「Python开发精选」分享 Python 技术文章、资源、课程、资讯。
点赞和在看就是最大的支持❤️